//
//  DWRuntimeViewController.m
//  OCAPPDemo
//
//  Created by 杨冬武 on 2022/9/18.
//

#import "DWRuntimeViewController.h"
#import "DWRuntime.h"
#import <objc/runtime.h>

@interface DWRuntimeViewController ()

@end

@implementation DWRuntimeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

- (IBAction)workingWithClasses:(id)sender {
    
    DWRuntime *rt = [[DWRuntime alloc] init];
    Class rtClass = [rt class];
    
    // 获取类的名字
    const char *name = class_getName([rt class]);
    NSLog(@"%s", name);
    
    // 获取父类
    Class superClass = class_getSuperclass(rtClass);
    NSLog(@"%s", class_getName(superClass));
    
    BOOL isMC0 = class_isMetaClass(superClass);
    NSLog(@"%s %@元类", class_getName(superClass), isMC0 ? @"是" : @"不是");
    
    
    id ssClass = object_getClass(rtClass);
    BOOL isMC1 = class_isMetaClass(ssClass);
    NSLog(@"%s %@元类", class_getName(ssClass), isMC1 ? @"是" : @"不是");
 
    // 获取属性占用内存大小
    size_t trISize = class_getInstanceSize(rtClass);
    NSLog(@"%s instance size = %zu", class_getName(rtClass), trISize);
    
    // 获取实例成员变量和类成员变量
    Ivar ivar = class_getInstanceVariable(rtClass, "_age");
    Ivar cvar = class_getClassVariable(rtClass, "isa");
    
    unsigned int count;
    Ivar *ivars = class_copyIvarList(rtClass, &count);
    for (int i = 0; i < count; i++) {
        Ivar var = ivars[i];
        const char *name = ivar_getName(var);
        const char *type = ivar_getTypeEncoding(var);
        NSLog(@"%s, %s", name, type);
    }
    free(ivars);
    
    // 获取成员变量的布局
    const uint8_t *array_s = class_getIvarLayout(rtClass);
    int i = 0;
    uint8_t value_s = array_s[i];
    while (value_s != 0x0) {
        printf("\\x%02x\n", value_s);
        value_s = array_s[++i];
    }
    
    
    // 获取属性
    objc_property_t p = class_getProperty(rtClass, "age");
    
    
    NSLog(@"%s", __FUNCTION__);
}


- (void)addIvar {
    /*
     1、该函数只有在动态添加的类中使用有效，且只能在objc_allocatelasspair()之后和objc_registerClassPair()之前调用，在已经存在的类中使用该函数无效；
     2、参数cls类不能是元类，不支持向元类添加实例变量；
     3、如果成功添加了实例变量，返回YES，否则返回NO（例如，该类已包含具有该名称的实例变量）。
     4、Ivar即(instance variable)简写，意为实例变量，也就是我们通常说的成员变量，它和@property属性不同，它没有自己的setter和getter方法。
     */
    Class rtClass = [DWRuntime class];
    BOOL addRes = class_addIvar(rtClass, "height", sizeof(int), log2(_Alignof(int)), @encode(int));
}




@end
